package org.linlinjava.litemall.web.service;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.linlinjava.litemall.core.util.AdminCouponDateUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.LitemallAccountBookFormDto;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.web.vo.GiftCardQueryResponseVO;
import org.linlinjava.litemall.web.vo.MemberQueryResponseVO;
import org.linlinjava.litemall.web.vo.RechargeConsumptionVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import static org.linlinjava.litemall.web.util.WebResponseCode.*;

@Service
@RequiredArgsConstructor
public class WebBalanceSrevice {

    private final LitemallUserService litemallUserService;

    private final LitemallGiftCardUserService giftCardService;

    private final LitemallGiftCardUserLogService litemallGiftCardUserLogService;

    private final LitemallRechargeTransactionsService litemallRechargeTransactionsService;

    private final LitemallRechargeConsumptionService litemallRechargeConsumptionService;

    private final LitemallAccountBookService litemallAccountBookService;

    private final LumiereCloverPayLogService lumiereCloverPayLogService;

    private final LumierelLevelMemberService lumierelLevelMemberService;
    private final LitemallCashScheduleService litemallCashScheduleService;

    private final LumiereCouponStrategyService lumiereCouponStrategyService;
    private final  LumiereCouponUserService lumiereCouponUserService;
    private final WebCouponService webCouponService;
    public ResponseUtil.Response enquiryAccount(String membershipCode) {
        LitemallUser litemallUser = litemallUserService.getOne(Wrappers.lambdaQuery(LitemallUser.class)
                .eq(LitemallUser::getMembershipNumber, membershipCode)
                .eq(LitemallUser::getInnerAccount,0));
        if(ObjectUtil.isNull(litemallUser)){
            return ResponseUtil.fail(401,"会员账号不存在");
        }
        if(litemallUser.getStatus().equals(3)){
            return ResponseUtil.fail(400,"该会员账号处于注销中");
        }
        return ResponseUtil.ok(litemallUser);
    }

    public ResponseUtil.Response rechargeByCash(BigDecimal amount, String membershipCode, Integer shopId,Integer userId,BigDecimal receiveAmount,String deviceNo) {
        LitemallUser litemallUser = litemallUserService.getOne(Wrappers.lambdaQuery(LitemallUser.class)
                .eq(LitemallUser::getMembershipNumber, membershipCode)
                .eq(LitemallUser::getInnerAccount,0));
        if(ObjectUtil.isNull(litemallUser)){
            return ResponseUtil.fail(401,"会员账号不存在");
        }
        if(amount.subtract(BigDecimal.ZERO).compareTo(BigDecimal.ZERO) <= 0){
            return ResponseUtil.fail(INVALID_RECHARGE_AMOUNT,"充值金额不正确");
        }
        litemallUser.setAvailableAmount(litemallUser.getAvailableAmount().add(amount));
        boolean b = litemallUserService.updateById(litemallUser);
        if(!b){
            return ResponseUtil.fail(402,"充值失败");
        }
        //充值记录
        LitemallRechargeConsumption rechargeConsumption = new LitemallRechargeConsumption();
        rechargeConsumption.setUserId(litemallUser.getId());
        rechargeConsumption.setMobile(litemallUser.getMobile());
        rechargeConsumption.setUsername(litemallUser.getUsername());
        rechargeConsumption.setUserLevel(litemallUser.getUserLevel());
        rechargeConsumption.setAvailableAmount(litemallUser.getAvailableAmount());
        rechargeConsumption.setPoints(litemallUser.getPoints());
        rechargeConsumption.setType((byte) 1);
        rechargeConsumption.setAmount(amount);
        rechargeConsumption.setDeleted(false);
        rechargeConsumption.setAddTime(LocalDateTime.now());
        rechargeConsumption.setAddUserId(userId);
        rechargeConsumption.setOrderSource(Constants.ORDER_SOURCE_POS);
        litemallRechargeConsumptionService.add(rechargeConsumption);


        //充值记录
        litemallRechargeTransactionsService.save(new LitemallRechargeTransactions()
                .setUserId(litemallUser.getId())
                .setShopId(shopId)
                .setUsername(litemallUser.getUsername())
                .setRechargeType(Constants.RECHARGE_TYPE_BALANCE)
                .setPayType(Constants.PAY_TYPE_CASH)
                .setRechargeAmount(amount)
                .setRechargeSource(Constants.ORDER_SOURCE_POS)
        );



        //记录现金交易
        LitemallCashSchedule cashSchedule = LitemallCashSchedule.builder()
                .userId(userId)
                .shopId(shopId)
                .type(3)
                .payTime(LocalDateTime.now())
                .orderCash(amount)
                .receiveCash(receiveAmount)
                .change(receiveAmount.subtract(amount))
                .actualCash(amount)
                .refundCash(BigDecimal.ZERO)
                .deviceNo(deviceNo)
                .build();
        litemallCashScheduleService.save(cashSchedule);

        //调用充值策略
        webCouponService.awardCoupon(litemallUser,amount,7,null);
        /*List<LumiereCouponStrategy> couponStrategyList = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType, 7)
                .eq(LumiereCouponStrategy::getStatus, 1));
        couponStrategyList.stream().forEach(couponStrategy -> {
            if(couponStrategy.getRechargeAmount().compareTo(amount)!=-1){
                //赠送券
                long nextId = IdUtil.getSnowflake(2, 2).nextId();
                LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(couponStrategy);
                LumiereCouponUser couponUser = LumiereCouponUser.builder()
                        .userId(userId)
                        .strategyId(couponStrategy.getId())
                        .couponId(couponStrategy.getCouponId())
                        .startTime(localDateTimes[0])
                        .endTime(localDateTimes[1])
                        .userName(litemallUser.getUsername())
                        .code(String.valueOf(nextId))
                        .addTime(LocalDateTime.now())
                        .updateTime(LocalDateTime.now())
                        .deleted(false)
                        .build();
                lumiereCouponUserService.save(couponUser);
            }
        });*/

        MemberQueryResponseVO response = new MemberQueryResponseVO();
        BeanUtils.copyProperties(litemallUser, response);
        //查询等级会员名称
        LumiereLevelMember levelMember = lumierelLevelMemberService.findById(response.getUserLevel().intValue());
        response.setLevelMember(ObjectUtil.isNotNull(levelMember)?levelMember.getName():"No membership level");
        addAccountBook(shopId,amount,"POSCash recharge",0,3);
        return ResponseUtil.ok(litemallUser);
    }
    private void addAccountBook(Integer shopId, BigDecimal actualPrice, String remark, Integer recordType, Integer sourceType) {
        LitemallAccountBookFormDto form = new LitemallAccountBookFormDto();
        form.setShopId(shopId);
        form.setRecordType(recordType);
        form.setRecordDate(LocalDateTime.now());
        form.setAmount(actualPrice);
        form.setRemark(remark);
        form.setSourceType(sourceType);
        litemallAccountBookService.create(shopId, form);
    }


    public ResponseUtil.Response rechargeSaveByClover(String externalId, String paymentId, String orderId,BigDecimal amount, String cardNo, String cardType, String membershipCode,Integer userId, Integer shopId) {
        LitemallUser litemallUser = litemallUserService.getOne(Wrappers.lambdaQuery(LitemallUser.class)
                .eq(LitemallUser::getMembershipNumber, membershipCode)
                .eq(LitemallUser::getInnerAccount,0));
        //用户加余额
        litemallUser.setAvailableAmount(litemallUser.getAvailableAmount().add(amount));
        litemallUserService.updateById(litemallUser);

        //充值记录
        LitemallRechargeConsumption rechargeConsumption = new LitemallRechargeConsumption();
        rechargeConsumption.setUserId(litemallUser.getId());
        rechargeConsumption.setMobile(litemallUser.getMobile());
        rechargeConsumption.setUsername(litemallUser.getUsername());
        rechargeConsumption.setUserLevel(litemallUser.getUserLevel());
        rechargeConsumption.setAvailableAmount(litemallUser.getAvailableAmount());
        rechargeConsumption.setPoints(litemallUser.getPoints());
        rechargeConsumption.setType((byte) 1);
        rechargeConsumption.setAmount(amount);
        rechargeConsumption.setDeleted(false);
        rechargeConsumption.setAddTime(LocalDateTime.now());
        rechargeConsumption.setAddUserId(userId);
        rechargeConsumption.setOrderSource(Constants.ORDER_SOURCE_POS);
        rechargeConsumption.setPayType(Constants.ORDER_PAY_TYPE_CLOVER.intValue());
        litemallRechargeConsumptionService.add(rechargeConsumption);

        //充值记录
        litemallRechargeTransactionsService.save(new LitemallRechargeTransactions()
                .setUserId(litemallUser.getId())
                .setShopId(shopId)
                .setUsername(litemallUser.getUsername())
                .setRechargeType(Constants.RECHARGE_TYPE_BALANCE)
                .setPayType(Constants.PAY_TYPE_CLOVER)
                .setRechargeAmount(amount)
                .setRechargeSource(Constants.ORDER_SOURCE_POS)
        );

        addAccountBook(shopId,amount,null,0,3);
        //clover支付记录
        LumiereCloverPayLog cloverPayLog = new LumiereCloverPayLog();
        cloverPayLog.setExternalId(externalId);
        cloverPayLog.setCardNo(cardNo);
        cloverPayLog.setPaymentId(paymentId);
        cloverPayLog.setOrderId(orderId);
        cloverPayLog.setCardType(cardType);
        cloverPayLog.setAddTime(LocalDateTime.now());
        cloverPayLog.setUpdateTime(LocalDateTime.now());
        cloverPayLog.setDeleted(false);
        lumiereCloverPayLogService.add(cloverPayLog);
        //调用充值策略
        webCouponService.awardCoupon(litemallUser,amount,7,null);
        MemberQueryResponseVO response = new MemberQueryResponseVO();
        BeanUtils.copyProperties(litemallUser, response);
        List<LumiereCouponStrategy> couponStrategyList = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType, 7)
                .eq(LumiereCouponStrategy::getStatus, 1));
        couponStrategyList.stream().forEach(couponStrategy -> {
            if(couponStrategy.getRechargeAmount().compareTo(amount)!=-1){
                //赠送券
                for (int i = 0; i < couponStrategy.getTotal(); i++) {
                    long nextId = IdUtil.getSnowflake(2, 2).nextId();
                    LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(couponStrategy);
                    LumiereCouponUser couponUser = LumiereCouponUser.builder()
                            .userId(userId)
                            .strategyId(couponStrategy.getId())
                            .couponId(couponStrategy.getCouponId())
                            .startTime(localDateTimes[0])
                            .endTime(localDateTimes[1])
                            .userName(litemallUser.getUsername())
                            .code(String.valueOf(nextId))
                            .addTime(LocalDateTime.now())
                            .updateTime(LocalDateTime.now())
                            .deleted(false)
                            .build();
                    lumiereCouponUserService.save(couponUser);
                }
            }
        });
        //查询等级会员名称
        LumiereLevelMember levelMember = lumierelLevelMemberService.findById(response.getUserLevel().intValue());
        response.setLevelMember(ObjectUtil.isNotNull(levelMember)?levelMember.getName():"No membership level");
        return ResponseUtil.ok(response);
    }

    public ResponseUtil.Response rechargeByGiftCard(String cardNo, BigDecimal amount, String membershipCode,Integer userId, Integer shopId) {
        if(amount.subtract(BigDecimal.ZERO).compareTo(BigDecimal.ZERO) <= 0){
            return ResponseUtil.fail(INVALID_RECHARGE_AMOUNT,"充值金额不正确");
        }
        LitemallUser litemallUser = litemallUserService.getOne(Wrappers.lambdaQuery(LitemallUser.class)
                .eq(LitemallUser::getMembershipNumber, membershipCode)
                .eq(LitemallUser::getInnerAccount,0));
        if(ObjectUtil.isNull(litemallUser)){
            return ResponseUtil.fail(401,"会员账号不存在");
        }
        LitemallGiftCardUser payGiftCard = giftCardService.findByNumber(cardNo);
        if(null == payGiftCard) {
            return ResponseUtil.badArgument(ORDER_PAY_IS_NULL_CARD, "礼物卡不存在");
        }
        if(payGiftCard.getAmount().compareTo(amount)==-1){
            return ResponseUtil.fail(ORDER_PAY_NOT_ENOUGH_AMOUNT,"支付余额不足");
        }
        litemallUser.setAvailableAmount(litemallUser.getAvailableAmount().add(amount));
        boolean b = litemallUserService.updateById(litemallUser);
        if(!b){
            return ResponseUtil.fail(402,"充值失败");
        }



        //充值记录
        LitemallRechargeConsumption rechargeConsumption = new LitemallRechargeConsumption();
        rechargeConsumption.setUserId(litemallUser.getId());
        rechargeConsumption.setMobile(litemallUser.getMobile());
        rechargeConsumption.setUsername(litemallUser.getUsername());
        rechargeConsumption.setUserLevel(litemallUser.getUserLevel());
        rechargeConsumption.setAvailableAmount(litemallUser.getAvailableAmount());
        rechargeConsumption.setPoints(litemallUser.getPoints());
        rechargeConsumption.setType((byte) 1);
        rechargeConsumption.setAmount(amount);
        rechargeConsumption.setDeleted(false);
        rechargeConsumption.setAddTime(LocalDateTime.now());
        rechargeConsumption.setAddUserId(userId);
        rechargeConsumption.setOrderSource(Constants.ORDER_SOURCE_POS);
        litemallRechargeConsumptionService.add(rechargeConsumption);
        addAccountBook(shopId,amount,"POSCash recharge",0,3);
        //支付的礼物卡
        BigDecimal payAmount = payGiftCard.getAmount().subtract(amount);
        payGiftCard.setAmount(payAmount);
        giftCardService.updateById(payGiftCard);
        LitemallGiftCardUserLog payLog = new LitemallGiftCardUserLog();
        payLog.setAmount(amount);
        payLog.setAddUserId(payGiftCard.getUserId());
        payLog.setType(Constants.LOG_GIFTCARD_CONSUME);
        payLog.setCardNumber(payGiftCard.getCardNumber());
        payLog.setCardUserId(payGiftCard.getId());
        payLog.setContent("pay"+amount);
        payLog.setOrderSource(Constants.ORDER_SOURCE_POS);
        payLog.setBalance(payGiftCard.getAmount());
        litemallGiftCardUserLogService.add(payLog);

        List<LumiereCouponStrategy> couponStrategyList = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType, 7)
                .eq(LumiereCouponStrategy::getStatus, 1));
        couponStrategyList.stream().forEach(couponStrategy -> {
            if(couponStrategy.getRechargeAmount().compareTo(amount)!=-1){
                //赠送券
                for (int i = 0; i < couponStrategy.getTotal(); i++) {
                    long nextId = IdUtil.getSnowflake(2, 2).nextId();
                    LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(couponStrategy);
                    LumiereCouponUser couponUser = LumiereCouponUser.builder()
                            .userId(userId)
                            .strategyId(couponStrategy.getId())
                            .couponId(couponStrategy.getCouponId())
                            .startTime(localDateTimes[0])
                            .endTime(localDateTimes[1])
                            .userName(litemallUser.getUsername())
                            .code(String.valueOf(nextId))
                            .addTime(LocalDateTime.now())
                            .updateTime(LocalDateTime.now())
                            .deleted(false)
                            .build();
                    lumiereCouponUserService.save(couponUser);
                }
            }
        });

        MemberQueryResponseVO response = new MemberQueryResponseVO();
        BeanUtils.copyProperties(litemallUser, response);
        //查询等级会员名称
        LumiereLevelMember levelMember = lumierelLevelMemberService.findById(response.getUserLevel().intValue());
        response.setLevelMember(ObjectUtil.isNotNull(levelMember)?levelMember.getName():"No membership level");

        addAccountBook(shopId,amount,null,1,3);
        return ResponseUtil.ok(response);
    }
}
